//
//  Multithreaded Hello World server
//

package main

import (
	"fmt"
	"os"
	"zmq"
)

var errch = make(chan os.Error)

func worker(context *zmq.Context, index int) os.Error {
	receiver, err := context.Socket(zmq.REP)
	if err != nil {
		return err
	}
	defer receiver.Close()
	err = receiver.Connect("inproc://workers")
	if err != nil {
		return err
	}
	for {
		d, err := receiver.Recv(0)
		if err != nil {
			return err
		}
		fmt.Printf("%d:%s.", index, d)
		zmq.Sleep(1)
		err = receiver.Send([]byte("World"), 0)
		if err != nil {
			return err
		}
	}
	return nil
}

func zmq_main() os.Error {
	context, err := zmq.Init(1)
	if err != nil {
		return err
	}
	defer context.Close()

	clients, err := context.Socket(zmq.ROUTER)
	if err != nil {
		return err
	}
	defer clients.Close()
	err = clients.Bind("tcp://*:5555")
	if err != nil {
		return err
	}

	workers, err := context.Socket(zmq.DEALER)
	if err != nil {
		return err
	}
	defer workers.Close()
	err = workers.Bind("inproc://workers")
	if err != nil {
		fmt.Println(err)
	}

	for i := 0; i < 5; i++ {
		go func(i int) {
			errch <- worker(context, i)
		}(i)
	}
	err = zmq.Device(zmq.QUEUE, clients, workers)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	fmt.Println("Multithreaded Hello World server")
	exit := make(chan bool)
	go func() {
		for {
			err := <-errch
			if err != nil {
				fmt.Println(err)
				os.Exit(2)
			}
		}
	}()
	go func() {
		err := zmq_main()
		if err != nil {
			errch <- err
		} else {	
			exit <- true
		}
	}()
	<-exit
}
